package com.easylinkin.linkappapi.security.config;

import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.common.constant.CommonConstant;
import com.easylinkin.linkappapi.operatelog.entity.CommonOperateLog;
import com.easylinkin.linkappapi.operatelog.service.CommonOperateLogService;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.entity.LinkappUserLoginInfo;
import com.easylinkin.linkappapi.security.service.LinkappUserLoginInfoService;
import com.easylinkin.linkappapi.security.service.LinkappUserService;
import com.easylinkin.linkappapi.security.service.TenantSessionService;
import com.easylinkin.sm.service.LogService;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Objects;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import site.morn.boot.web.Responses;
import site.morn.framework.context.AccountContext;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

/**
 * 认证成功处理者
 *
 * @author timely-rain
 * @since 1.2.0, 2019/8/29
 */
@Slf4j
@Component
public class LinkappRestAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Autowired
    private LinkappUserLoginInfoService userLoginInfoService;
    @Autowired
    private LinkappUserService userService;
    @Autowired
    private LogService logService;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private LoginCountCheck loginCountCheck;
    @Resource
    private TenantSessionService tenantSessionService;
    @Resource
    private CommonOperateLogService commonOperateLogService;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) {
        LinkappUser user;
        String username = null;
        String ssoToken = request.getParameter("ssoToken");
        String content = "登录成功";
        String phone = request.getParameter("phone");
        boolean isSsoLogin = false;
        if (ssoToken == null || ssoToken.length() == 0) {
            if (phone == null || phone.length() == 0) {
                username = request.getParameter("username");
                user = userService.findByUsername(username);
                content = "账号" + content;
            } else {
                user = (LinkappUser) redisUtil.get(phone + "_login");
                request.setAttribute("username", user.getUsername());
                content = "短信" + content;
            }
        } else {
            isSsoLogin = true;
            user = (LinkappUser) redisUtil.get(ssoToken);
            request.setAttribute("username", user.getUsername());
        }

        CommonOperateLog commonOperateLog = new CommonOperateLog();
        if (user != null) {
            commonOperateLog.setTenantId(user.getTenantId());
            commonOperateLog.setPhone(user.getPhone());
            commonOperateLog.setUserAccount(user.getUsername());
            commonOperateLog.setNickname(user.getNickname());
        }
        String platform = request.getHeader("platform");
        if(StringUtils.isNotEmpty(platform)){
            commonOperateLog.setPlatform(platform);
        }
        commonOperateLog.setModuleName("登录");
        commonOperateLog.setContent(content);
        commonOperateLog.setCreateTime(new Date()).setResult(true);
        commonOperateLogService.addLog(commonOperateLog);

        LinkappUserLoginInfo userLoginInfo = userLoginInfoService.get(user.getId());
        if (Objects.nonNull(userLoginInfo)) {
            userLoginInfoService.clear(user.getId());
        }

        // 清空登录缓存
        AccountContext.cacheGroup().clearKey(authentication.getName());

        try {
            if (isSsoLogin) {
                StringBuilder s = new StringBuilder();
                s.append("<!DOCTYPE html>")
                        .append("<html lang=\"zh-CN\">")
                        .append("<head>")
                        .append("<script>")
                        .append("sessionStorage.setItem('sso-login', 'true');")
                        .append("location.href = location.origin;")
                        .append("</script>")
                        .append("</head>")
                        .append("</html>");

                response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                response.setContentType(MediaType.TEXT_HTML_VALUE);
                response.getWriter().write(s.toString());
            } else {
                HttpSession session = request.getSession();
                if (user != null) {
                    Integer timeout;
                    String sessionTimeout = request.getParameter("sessionTimeout");
                    if(StringUtils.isNotBlank(sessionTimeout)){
                        timeout = Integer.valueOf(sessionTimeout);
                    }else {
                        timeout = tenantSessionService.getTimeout(user.getTenantId());
                    }
                    session.setMaxInactiveInterval(timeout);
                }else {
                    session.setMaxInactiveInterval(CommonConstant.SESSION_TIME_DEFAULT);
                }

                RestMessage message = RestBuilders.successMessage("login.success");
                Responses.standard(response).respond(message);
            }
        } catch (IOException e) {
            LinkappRestAuthenticationSuccessHandler.log.error(e.getMessage(), e);
        }

        loginCountCheck.afterLoginHandler(true, user.getUsername());
    }
}
